﻿using System;
using System.Numerics;
using UtilZ.Dotnet.Ex.Base;

namespace UtilZ.Dotnet.Ex.Normalization
{
#pragma warning disable 8500
    unsafe internal class InnerNormalizer_Byte<TResult> : InnerNormalizerAbs<byte, TResult>
#if CORE
            where TResult : struct, IComparable<TResult>, INumberBase<TResult>
#else
            where TResult : struct, IComparable<TResult>
#endif
    {
        public InnerNormalizer_Byte(NormalizerOptions options, bool useMap)
             : base(options, useMap ? true : false)
        {

        }


        protected override TResult PrimitiveExcute(byte source, double factor, double inputOffset, double outputOffset)
        {
            return base.ConvertToResult((source - inputOffset) * factor + outputOffset);
        }

        protected override TResult PrimitiveExcuteMap(byte source, TResult[] resultArr, long indexOffset)
        {
            int index = (int)(source - indexOffset);
            if (index < 0)
            {
                index = 0;
            }
            else if (index >= resultArr.Length)
            {
                index = resultArr.Length - 1;
            }

            return resultArr[index];
        }

        protected override void PrimitiveExcute(byte* sourcePtr, TResult* destPtr, int length, double outputOffset)
        {
            var minMax = EnumerableEx.FindMinMaxIndex(sourcePtr, length);
            double inputOffset;
            var factor = base.CaculateNormalizeFactor(minMax.MinValue.Value, minMax.MaxValue.Value, out inputOffset);
            if (double.IsNaN(factor))
            {
                base.FactorNaNFill(destPtr, length);
            }
            else
            {
                for (int i = 0; i < length; i++)
                {
                    destPtr[i] = base.ConvertToResult((sourcePtr[i] - inputOffset) * factor + outputOffset);
                }
            }
        }

        protected override void PrimitiveExcuteMap(byte* sourcePtr, TResult* destPtr, int length, TResult[] resultArr, long indexOffset)
        {
            int index;
            for (int i = 0; i < length; i++)
            {
                index = (int)(sourcePtr[i] - indexOffset);
                if (index < 0)
                {
                    index = 0;
                }
                else if (index >= resultArr.Length)
                {
                    index = resultArr.Length - 1;
                }

                destPtr[i] = resultArr[index];
            }
        }

    }

}
